Comparing Responses from Initial, evaluate and Accelerate

  1. Load data

library(dplyr)
library(plotly)
library(ggplot2)
library(wesanderson)

source("custom_functions.R")

registration = load("../processed data/registration.RData")

load("../../Evaluate/processed data/comparison_evaluate.RData",  temp_env <- new.env())
evaluate <- as.list(temp_env)

load("../processed data/comparison_accelerate.RData",  temp_env <- new.env())
accelerate = as.list(temp_env)

map = read.csv("../data/team_users_hashed.csv")
colnames(map) = c("Team", "ID", "Hash", "Mentors")

reg = merge(reg, map[,c("Team", "Hash")], by.x = "ID", by.y = "Hash")


reg_map = c("A2: Women & Technology Against Climate Change" = "T6: Women & Technology Against Climate Change", "B2: TEAM FOILED" = "T3: TEAM FOILED", "C1: Andapé Institute" = "T13: Andapé Institute", "C3: WOMER" = "T5: WOMER", "A5: Donate Water Project" = "T9: DonateWater", "B5: Rights of Climate" = "T11: Rights of Climate", "B3: Eco Winners" = "T14: Eco Winners", "B4: Women 4 Sustainable World" = "T12: Women 4 Sustainable World", "A1: Up Get App/CitiCERN" = "T7: UpGet app - CitiCERN Project", "B1: Water Warriors" = "T10: Water Warriors", "C2: PAM" = "T4: PAM", "C4: Climate Gender Justice" = "T8: Climate Gender Justice", "A3: Rhythm of Bamboos" = "T1: SDesiGn (Old name: Rhythm of Bamboos)", "C5: Ashifa Nazrin" = "C5: Ashifa Nazrin", "A4: Flood Rangers" = "T2: Flood Rangers")

reg_map = data.frame(old_name = names(reg_map), new_name = reg_map)
reg = merge(reg, reg_map, by.x = "Team", by.y = "old_name", all.x = TRUE)
  1. Learning “Exante” questions

two questions with multiple correct answers. Counting - one point for a correct answer. 0 for wrong

(Correct Team Names)

library(tidyr)

correct_k = c("National Statistical Offices have reservations on the use of citizen science data due to quality considerations.", "Impartiality (independence) and confidentiality are among key principles for official national data producers.")

correct_d = c("Collect data", "Analyze data","Share own data")

temp_reg = reg[,c("exante_knowledge", "exante_data", "Team", "ID")]
temp_reg = reshape2::melt(temp_reg, id = c("Team", "ID"))
Warning: attributes are not identical across measure variables; they will be dropped
temp_reg = temp_reg %>% rowwise() %>% mutate(answers = list(trimws(strsplit(value, ",")[[1]]))) %>% mutate(correct =  if (variable == "exante_knowledge") sum(answers %in% correct_k)/length(correct_k) else sum(answers %in% correct_d)/length(correct_d), hyper = if (variable == "exante_knowledge") phyper(sum(answers %in% correct_k), 2, 2, length(answers), lower.tail = FALSE) else phyper(sum(answers %in% correct_d), 3, 1, length(answers), lower.tail = FALSE))

  #mutate(correct = if ((sum(answers %in% correct_k) == length(answers) & length(answers) == 2) || (sum(answers %in% correct_d) == length(answers) & length(answers) == 3)) 1  else 0)

temp_reg$type = "registration"

temp_evaluate = as.data.frame(evaluate["ext"])
colnames(temp_evaluate) = c("ID", "Team", "exante_knowledge", "exante_data")
temp_evaluate = reshape2::melt(temp_evaluate, id = c("Team", "ID"))
Warning: attributes are not identical across measure variables; they will be dropped
temp_evaluate = temp_evaluate %>% rowwise() %>% mutate(answers = list(trimws(strsplit(value, ";")[[1]]))) %>% mutate(correct =  if (variable == "exante_knowledge") sum(answers %in% correct_k)/length(correct_k) else sum(answers %in% correct_d)/length(correct_d), hyper = if (variable == "exante_knowledge") phyper(sum(answers %in% correct_k), 2, 2, length(answers), lower.tail = FALSE) else phyper(sum(answers %in% correct_d), 3, 1, length(answers), lower.tail = FALSE))

#mutate(correct = if ((sum(answers %in% correct_k) == length(answers) & length(answers) == 2) || (sum(answers %in% correct_d) == length(answers) & length(answers) == 3)) 1  else 0)

temp_evaluate$type = "evaluate"

temp_accelerate = as.data.frame(accelerate["ext"])
colnames(temp_accelerate) = c("ID", "Team", "exante_knowledge", "exante_data")
temp_accelerate = reshape2::melt(temp_accelerate, id = c("Team", "ID"))
Warning: attributes are not identical across measure variables; they will be dropped
temp_accelerate = temp_accelerate %>% rowwise() %>% mutate(answers = list(trimws(strsplit(value, ";")[[1]]))) %>% mutate(correct =  if (variable == "exante_knowledge") sum(answers %in% correct_k)/length(correct_k) else sum(answers %in% correct_d)/length(correct_d), hyper = if (variable == "exante_knowledge") phyper(sum(answers %in% correct_k), 2, 2, length(answers), lower.tail = FALSE) else phyper(sum(answers %in% correct_d), 3, 1, length(answers), lower.tail = FALSE))
  
  #mutate(correct = if ((sum(answers %in% correct_k) == length(answers) & length(answers) == 2) || (sum(answers %in% correct_d) == length(answers) & length(answers) == 3)) 1  else 0)

temp_accelerate$type = "accelerate"

df = rbind(temp_reg, temp_evaluate, temp_accelerate)
df$type = factor(df$type, levels = c("registration", "evaluate", "accelerate"))

df1 = df[,c("type", "variable", "hyper")] %>% group_by(variable, type) %>% summarise(mean = mean(hyper), se = se(hyper))
`summarise()` has grouped output by 'variable'. You can override using the `.groups` argument.
plt = ggplot(df1, aes(x = type, y = mean, color = variable, group = variable)) + geom_line() + geom_errorbar(aes(ymin = mean-se, ymax = mean+se), width = 0) + theme_bw(base_size = 20) + ylab("HypG P-Value") + xlab("")

ggsave(plt, file = "../figures/exante_compare_hypg.png", height = 7, width = 7)

#****#

df1 = df[,c("type", "variable", "correct")] %>% group_by(variable, type) %>% summarise(mean = mean(correct), se = se(correct))
`summarise()` has grouped output by 'variable'. You can override using the `.groups` argument.
df1$variable = as.character(df1$variable)
df1$variable[df1$variable == "exante_data"] = "Data production by citizen scientists"
df1$variable[df1$variable == "exante_knowledge"] = "Knowledge on citizen science data"

plt = ggplot(df1, aes(x = type, y = mean, color = variable, group = variable)) + geom_line() + geom_errorbar(aes(ymin = mean-se, ymax = mean+se), width = 0) + theme_bw(base_size = 20) + xlab("") + ylab("Proportion Correct Answer") + theme(legend.title = element_blank())

ggsave(plt, file = "../figures/exante_compare.png", height = 7, width = 10)
  1. Tools and Learning about tools
library(fmsb)

re_tools = reg[,c("ID", "Team", "tools")]
re_tools$tools = as.character(re_tools$tools)
re_tools = re_tools %>% rowwise() %>% mutate(tools = list(trimws(strsplit(tools, ",")[[1]])))
re_tools = unnest(re_tools, cols = c("tools"))
re_tools$type = "registration"

el_tools = as.data.frame(evaluate["cs_tools"])
colnames(el_tools) = c("ID", "Team", "variable", "tools")
el_tools = el_tools[] %>% rowwise() %>% mutate(tools = list(trimws(strsplit(tools, ";")[[1]]))) %>% select(-variable)
el_tools = unnest(el_tools, cols = c("tools"))
el_tools$type = "evaluate"

ac_tools = as.data.frame(accelerate["cs_tools"])
colnames(ac_tools) = c("ID", "Team", "variable", "tools")
ac_tools = ac_tools[] %>% rowwise() %>% mutate(tools = list(trimws(strsplit(tools, ";")[[1]]))) %>% select(-variable)
ac_tools = unnest(ac_tools, cols = c("tools"))
ac_tools$type = "accelerate"

Radar Plot - All teams


re_tools = merge(re_tools, reg_map, by.x = "Team", by.y = "old_name", all.x = TRUE)
re_tools$Team = re_tools$new_name

re_tools = re_tools %>% select(-new_name)

tools = rbind(re_tools, el_tools, ac_tools)
tools$tools[tools$tools == "None of the above"] = "None"

temp = tools %>% group_by(tools, type) %>% summarise(count = n())
`summarise()` has grouped output by 'tools'. You can override using the `.groups` argument.
temp = temp %>% group_by(type) %>% mutate(count = count/sum(count))
temp = reshape2::acast(temp, type~tools)
Using count as value column: use value.var to override.
temp[is.na(temp)] = 0

temp = rbind(rep(1, ncol(temp)), rep(0,ncol(temp)), temp)
temp = as.data.frame(temp)

colors_border=c( rgb(0.2,0.5,0.5,0.9), rgb(0.8,0.2,0.5,0.9) , rgb(0.7,0.5,0.1,0.9) )
colors_in=c( rgb(0.2,0.5,0.5,0.4), rgb(0.8,0.2,0.5,0.4) , rgb(0.7,0.5,0.1,0.4) )

pdf("../figures/radar_stage.pdf", paper="a4r", width=10, height=10)

radarchart( as.data.frame(temp), axistype=1 , 
    #custom polygon
    pcol=colors_border , pfcol=colors_in , plwd=4 , plty=1,
    #custom the grid
    cglcol="grey", cglty=1, axislabcol="grey", cglwd=0.8,
    #custom labels
    vlcex=1.5 
    )

legend(x=1.2, y=1, legend = rownames(temp[c(5,4,3),]), bty = "n", pch=20 , col=colors_in[c(3,2,1)] , text.col = "grey", cex=1.2, pt.cex=3)

dev.off()
null device 
          1 

Only Teams in Accelerate


temp = tools[tools$Team %in% unique(tools$Team[tools$type == "accelerate"]),]
temp = temp %>% group_by(tools, type) %>% summarise(count = n())
`summarise()` has grouped output by 'tools'. You can override using the `.groups` argument.
temp = temp %>% group_by(type) %>% mutate(count = count/sum(count)) 
temp = reshape2::acast(temp, type~tools)
Using count as value column: use value.var to override.
temp[is.na(temp)] = 0

temp = rbind(rep(1, ncol(temp)), rep(0,ncol(temp)), temp)
temp = as.data.frame(temp)

colors_border=c( rgb(0.2,0.5,0.5,0.9), rgb(0.8,0.2,0.5,0.9) , rgb(0.7,0.5,0.1,0.9) )
colors_in=c( rgb(0.2,0.5,0.5,0.4), rgb(0.8,0.2,0.5,0.4) , rgb(0.7,0.5,0.1,0.4) )

pdf("../figures/radar_teams.pdf", paper="a4r", width=10, height=10)

radarchart( as.data.frame(temp), axistype=1 , 
    #custom polygon
    pcol=colors_border , pfcol=colors_in , plwd=4 , plty=1,
    #custom the grid
    cglcol="grey", cglty=1, axislabcol="grey", cglwd=0.8,
    #custom labels
    vlcex=1.5 
    )

legend(x=1.2, y=1, legend = rownames(temp[c(5,4,3),]), bty = "n", pch=20 , col=colors_in[c(3,2,1)] , text.col = "grey", cex=1.2, pt.cex=3)

dev.off()
null device 
          1 
  1. How Often did you connect with relevant people

el_ho = as.data.frame(evaluate["h_o"])
colnames(el_ho) = c("ID", "Team", "variable", "value", "score")
el_ho$type = "evaluate"


ac_ho = as.data.frame(accelerate["h_o"])
colnames(ac_ho) = c("ID", "Team", "variable", "value", "score")
ac_ho$type = "accelerate"

ho = rbind(el_ho, ac_ho)
ho$type = factor(ho$type, levels = c("evaluate", "accelerate"))

val = sort(factor(unique(ho$value), levels = c("Never", "Less than once a week", "Once a week", "Two to three times a week", "Four times or more a week")))

ho_t = ho %>% group_by(type, variable) %>% summarise(mean = mean(score), se = se(score))
`summarise()` has grouped output by 'type'. You can override using the `.groups` argument.
plt = ggplot(ho_t, aes(x = variable, y = mean, fill = type, color = type)) + geom_point(position = position_dodge(width = 0.3, preserve = "total")) + geom_errorbar(aes(ymin = mean-se, ymax = mean+se), position = position_dodge(width = 0.3, preserve = "total"), width = 0) + theme_bw(base_size = 22) + scale_y_continuous(labels=c(0:4), breaks=0:4, limits=c(0,4)) + ylab("") + xlab("") + theme(legend.title = element_blank())

ggplotly(plt)

ggsave(plt, filename = "../figures/how_often_compare.png", width = 10, height = 5)

By Team1


ho$status = "evaluate"
ho$status[ho$Team %in% unique(ho$Team[ho$type == "accelerate"])] = "accelerate"

ho$status = factor(ho$status, levels = c("evaluate", "accelerate"))

ho_t = ho %>% group_by(type, variable, status) %>% summarise(mean = mean(score), se = se(score), count = n())
`summarise()` has grouped output by 'type', 'variable'. You can override using the `.groups` argument.
plt = ggplot(ho_t[ho_t$type == "evaluate",], aes(x = variable, y = mean, fill = status, color = status)) + geom_point(position = position_dodge(width = 0.3, preserve = "total")) + geom_errorbar(aes(ymin = mean-se, ymax = mean+se), position = position_dodge(width = 0.3, preserve = "total"), width = 0) + theme_bw(base_size = 22)  + ylab("") + xlab("") + ggtitle("How often did you connect with these people \n for feedback and support for your team project?") + scale_y_continuous(labels=val, breaks=0:4, limits=c(0,4))+ theme(legend.title = element_blank()) + theme(plot.title = element_text(hjust = 0.5, size = 20))

ggplotly(plt)

ggsave(plt, filename = "../figures/how_often_evaluate.png", width = 10, height = 5)

Communication Tools (No Slack option in evaluate - There is Other listed, but frequency is unsure)


el_wc = as.data.frame(evaluate["w_c"])
colnames(el_wc) = c("ID", "Team", "variable", "value", "score")
el_wc$type = "evaluate"

ac_wc = as.data.frame(accelerate["w_c"])
colnames(ac_wc) = c("ID", "Team", "variable", "value", "score")
ac_wc$type = "accelerate"

wc = rbind(el_wc, ac_wc)

val = sort(factor(unique(wc$value), levels = c("Never", "Rarely", "Sometimes", "Often", "Always")))

wc_t = wc %>% group_by(type, variable) %>% summarise(mean = mean(score), se = se(score))
`summarise()` has grouped output by 'type'. You can override using the `.groups` argument.
plt = ggplot(wc_t[!wc_t$variable == "Other...specify.in.next.question..",], aes(x = variable, y = mean, fill = type, color = type)) + geom_point(position = position_dodge(width = 0.3, preserve = "total")) + geom_errorbar(aes(ymin = mean-se, ymax = mean+se), position = position_dodge(width = 0.3, preserve = "total"), width = 0) + theme_bw(base_size = 20) + scale_y_continuous(labels=val, breaks=0:4, limits=c(0,4)) + ylab("") + xlab("") + theme(axis.text.x = element_text(angle = 45))+ theme(legend.title = element_blank())

ggplotly(plt)

Issues (not very helpful)


el_di = as.data.frame(evaluate["d_i"])
colnames(el_di) = c("ID", "Team", "variable", "value", "score")
el_di$type = "evaluate"

ac_di = as.data.frame(accelerate["d_i"])
colnames(ac_di) = c("ID", "Team", "variable", "value", "score")
ac_di$type = "accelerate"

di = rbind(el_di, ac_di)
di$type = factor(di$type, levels = c("evaluate", "accelerate"))

val = sort(factor(unique(di$value), levels = c("Never", "Rarely", "Sometimes", "Often", "Always")))

di_t = di %>% group_by(type, variable) %>% summarise(mean = mean(score), se = se(score))
`summarise()` has grouped output by 'type'. You can override using the `.groups` argument.
plt = ggplot(di_t, aes(x = variable, y = mean, fill = type, color = type)) + geom_point(position = position_dodge(width = 0.3, preserve = "total")) + geom_errorbar(aes(ymin = mean-se, ymax = mean+se), position = position_dodge(width = 0.3, preserve = "total"), width = 0) + theme_bw(base_size = 20)  + ylab("") + xlab("") + theme(axis.text.x = element_text(angle = 0)) + scale_y_continuous(labels=val, breaks=0:4, limits=c(0,4))+ theme(legend.title = element_blank())

ggplotly(plt)

ggsave(plt, filename = "../figures/had_issues_compare.png", width = 10, height = 7)

Issues (Only Accelerate Teams)


di_t = di[di$Team %in% unique(di$Team[di$type == "accelerate"]),] %>% group_by(type, variable) %>% summarise(mean = mean(score), se = se(score))
`summarise()` has grouped output by 'type'. You can override using the `.groups` argument.
plt = ggplot(di_t, aes(x = variable, y = mean, fill = type, color = type)) + geom_point(position = position_dodge(width = 0.3, preserve = "total")) + geom_errorbar(aes(ymin = mean-se, ymax = mean+se), position = position_dodge(width = 0.3, preserve = "total"), width = 0) + theme_bw(base_size = 20)  + ylab("") + xlab("") + theme(axis.text.x = element_text(angle = 0)) + scale_y_continuous(labels=val, breaks=0:4, limits=c(0,4))+ theme(legend.title = element_blank())

ggplotly(plt)

ggsave(plt, filename = "../figures/had_issues_compare_acc_teams.png", width = 10, height = 7)

Gender Analysis


acc_team = as.character(unique(accelerate[[1]]$What.is.your.team.))

gen = reg[,c("gender", "Team")]
#gen$Teaml = reg_map[gen$Team]
gen = merge(gen, reg_map, by.x = "Team", by.y = "old_name", all.x = TRUE)
gen$Team = gen$new_name
gen = gen %>% select(-new_name)

temp = gen %>% group_by(Team, gender) %>% summarise(count = n())
`summarise()` has grouped output by 'Team'. You can override using the `.groups` argument.
temp$type = 1
temp$type[temp$Team %in% acc_team] = 2

col = wes_palette("GrandBudapest1", 3)
#col = hp(n = 3, option = "LunaLovegood")

temp$gender = factor(temp$gender, levels = c("Prefer not to say", "Male", "Female" ))

plt = ggplot(temp, aes(x = count, y = reorder(Team, type), fill = gender)) + geom_bar(stat = "identity") + theme_bw(base_size = 22) + ylab("") + xlab("") + scale_fill_manual(values = c(col[1], col[2], col[3])) + theme(legend.title = element_blank()) #+ geom_text(stat='identity', aes(label= count), hjust=-1)

ggplotly(plt)

ggsave(plt, filename = "../figures/gender_dist.png", height = 5, width = 15)

Background Radar


back = reg[ ,c("new_name", "background")]

back = clean_split_mcq(back)
colnames(back) = c("Team", "bgr")

#back$background = as.character(back$background)
#back = back %>% rowwise() %>% mutate(bgr = list(trimws(strsplit(background, ",")[[1]])))

#back = unnest(back, cols = c("bgr"))

temp = back[back$Team %in% acc_team,] %>% group_by(bgr, Team) %>% summarise(count = n())
`summarise()` has grouped output by 'bgr'. You can override using the `.groups` argument.
temp = reshape2::acast(temp, formula = Team~bgr)
Using count as value column: use value.var to override.
temp[is.na(temp)] = 0

temp = rbind(rep(4, ncol(temp)), rep(0,ncol(temp)), temp)
temp = as.data.frame(temp)

#colors_border=c( rgb(0.2,0.5,0.5,0.9), rgb(0.8,0.2,0.5,0.9) , rgb(0.7,0.5,0.1,0.9) )
#colors_in=c( rgb(0.2,0.5,0.5,0.4), rgb(0.8,0.2,0.5,0.4) , rgb(0.7,0.5,0.1,0.4) )

png(filename = "../figures/reg_background.png")

radarchart( as.data.frame(temp), axistype=1 , 
    #custom polygon
    plwd=4 , plty=1,
    #custom the grid
    cglcol="grey", cglty=1, axislabcol="grey", cglwd=0.8,
    #custom labels
    vlcex=0.5 
    )

legend(x=1.4, y=1, legend = rownames(temp[c(5,4,3),]), bty = "n", pch=20 , col=colors_in[c(3,2,1)] , text.col = "grey", cex=1.2, pt.cex=3)

dev.off()
null device 
          1 

Sankey Networks


library(networkD3)
library(rbokeh)

Attaching package: ‘rbokeh’

The following object is masked from ‘package:sjPlot’:

    set_theme
library(webshot)

for (i in c("gender", "country_orig", "country_resid", "education", "communication", "exante_project_SDG", "background", "occupation"))
{
  
  temp = reg[ ,c("new_name", i)]
  
  temp = clean_split_mcq(temp)
  colnames(temp) = c("Team", "var")
  
  nodes = data.frame(Name = union(unique(temp$Team), unique(temp$var)))

  links = temp %>% group_by(Team, var) %>% summarise(count = n())
  links$IDsource <- match(links$Team, nodes$Name)-1 
  links$IDtarget <- match(links$var, nodes$Name)-1

  plt = sankeyNetwork(Links = links, Nodes = nodes,
                     Source = "IDsource", Target = "IDtarget",
                     Value = "count", NodeID = "Name", 
                     sinksRight=FALSE, fontSize = 15)
  #plt
  
  visSave(plt, paste("../figures/sankey/", i, "_reg.html", sep = ""))
  #widget2png(plt, paste("../figures/sankey/", i, "_reg.png", sep = ""))
  
  webshot(paste("../figures/sankey/", i, "_reg.html", sep = ""), paste("../figures/sankey/", i, "_reg.png", sep = ""))
}
`summarise()` has grouped output by 'Team'. You can override using the `.groups` argument.
Links is a tbl_df. Converting to a plain data frame.
`summarise()` has grouped output by 'Team'. You can override using the `.groups` argument.
Links is a tbl_df. Converting to a plain data frame.
`summarise()` has grouped output by 'Team'. You can override using the `.groups` argument.
Links is a tbl_df. Converting to a plain data frame.
`summarise()` has grouped output by 'Team'. You can override using the `.groups` argument.
Links is a tbl_df. Converting to a plain data frame.
`summarise()` has grouped output by 'Team'. You can override using the `.groups` argument.
Links is a tbl_df. Converting to a plain data frame.
`summarise()` has grouped output by 'Team'. You can override using the `.groups` argument.
Links is a tbl_df. Converting to a plain data frame.
`summarise()` has grouped output by 'Team'. You can override using the `.groups` argument.
Links is a tbl_df. Converting to a plain data frame.
`summarise()` has grouped output by 'Team'. You can override using the `.groups` argument.
Links is a tbl_df. Converting to a plain data frame.

Age by Gender


reg$age = floor(as.numeric(difftime(as.Date("2022-04-01"), as.Date(reg$birthday, tryFormats = c("%m/%d/%Y")), unit="weeks"))/52.25)

plt = ggplot(reg, aes(x = gender, y = age)) + geom_boxplot(fill = "gray") + theme_bw(base_size = 20) + xlab("") + ylab("Age") + geom_point(aes(x = gender, y = age), alpha = 0.2)
ggplotly(plt)

ggsave(plt, filename = "../figures/age_gender.png", height = 7, width = 5)
LS0tCnRpdGxlOiAiQ29tcGFyaW5nIEFuc3dlcnMiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCkNvbXBhcmluZyBSZXNwb25zZXMgZnJvbSBJbml0aWFsLCBldmFsdWF0ZSBhbmQgQWNjZWxlcmF0ZQoKMC4gTG9hZCBkYXRhCgpgYGB7cn0KCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkocGxvdGx5KQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkod2VzYW5kZXJzb24pCgpzb3VyY2UoImN1c3RvbV9mdW5jdGlvbnMuUiIpCgpyZWdpc3RyYXRpb24gPSBsb2FkKCIuLi9wcm9jZXNzZWQgZGF0YS9yZWdpc3RyYXRpb24uUkRhdGEiKQoKbG9hZCgiLi4vLi4vRXZhbHVhdGUvcHJvY2Vzc2VkIGRhdGEvY29tcGFyaXNvbl9ldmFsdWF0ZS5SRGF0YSIsICB0ZW1wX2VudiA8LSBuZXcuZW52KCkpCmV2YWx1YXRlIDwtIGFzLmxpc3QodGVtcF9lbnYpCgpsb2FkKCIuLi9wcm9jZXNzZWQgZGF0YS9jb21wYXJpc29uX2FjY2VsZXJhdGUuUkRhdGEiLCAgdGVtcF9lbnYgPC0gbmV3LmVudigpKQphY2NlbGVyYXRlID0gYXMubGlzdCh0ZW1wX2VudikKCm1hcCA9IHJlYWQuY3N2KCIuLi9kYXRhL3RlYW1fdXNlcnNfaGFzaGVkLmNzdiIpCmNvbG5hbWVzKG1hcCkgPSBjKCJUZWFtIiwgIklEIiwgIkhhc2giLCAiTWVudG9ycyIpCgpyZWcgPSBtZXJnZShyZWcsIG1hcFssYygiVGVhbSIsICJIYXNoIildLCBieS54ID0gIklEIiwgYnkueSA9ICJIYXNoIikKCgpyZWdfbWFwID0gYygiQTI6IFdvbWVuICYgVGVjaG5vbG9neSBBZ2FpbnN0IENsaW1hdGUgQ2hhbmdlIiA9ICJUNjogV29tZW4gJiBUZWNobm9sb2d5IEFnYWluc3QgQ2xpbWF0ZSBDaGFuZ2UiLCAiQjI6IFRFQU0gRk9JTEVEIiA9ICJUMzogVEVBTSBGT0lMRUQiLCAiQzE6IEFuZGFww6kgSW5zdGl0dXRlIiA9ICJUMTM6IEFuZGFww6kgSW5zdGl0dXRlIiwgIkMzOiBXT01FUiIgPSAiVDU6IFdPTUVSIiwgIkE1OiBEb25hdGUgV2F0ZXIgUHJvamVjdCIgPSAiVDk6IERvbmF0ZVdhdGVyIiwgIkI1OiBSaWdodHMgb2YgQ2xpbWF0ZSIgPSAiVDExOiBSaWdodHMgb2YgQ2xpbWF0ZSIsICJCMzogRWNvIFdpbm5lcnMiID0gIlQxNDogRWNvIFdpbm5lcnMiLCAiQjQ6IFdvbWVuIDQgU3VzdGFpbmFibGUgV29ybGQiID0gIlQxMjogV29tZW4gNCBTdXN0YWluYWJsZSBXb3JsZCIsICJBMTogVXAgR2V0IEFwcC9DaXRpQ0VSTiIgPSAiVDc6IFVwR2V0IGFwcCAtIENpdGlDRVJOIFByb2plY3QiLCAiQjE6IFdhdGVyIFdhcnJpb3JzIiA9ICJUMTA6IFdhdGVyIFdhcnJpb3JzIiwgIkMyOiBQQU0iID0gIlQ0OiBQQU0iLCAiQzQ6IENsaW1hdGUgR2VuZGVyIEp1c3RpY2UiID0gIlQ4OiBDbGltYXRlIEdlbmRlciBKdXN0aWNlIiwgIkEzOiBSaHl0aG0gb2YgQmFtYm9vcyIgPSAiVDE6IFNEZXNpR24gKE9sZCBuYW1lOiBSaHl0aG0gb2YgQmFtYm9vcykiLCAiQzU6IEFzaGlmYSBOYXpyaW4iID0gIkM1OiBBc2hpZmEgTmF6cmluIiwgIkE0OiBGbG9vZCBSYW5nZXJzIiA9ICJUMjogRmxvb2QgUmFuZ2VycyIpCgpyZWdfbWFwID0gZGF0YS5mcmFtZShvbGRfbmFtZSA9IG5hbWVzKHJlZ19tYXApLCBuZXdfbmFtZSA9IHJlZ19tYXApCnJlZyA9IG1lcmdlKHJlZywgcmVnX21hcCwgYnkueCA9ICJUZWFtIiwgYnkueSA9ICJvbGRfbmFtZSIsIGFsbC54ID0gVFJVRSkKCmBgYAoKMS4gTGVhcm5pbmcgIkV4YW50ZSIgcXVlc3Rpb25zCgp0d28gcXVlc3Rpb25zIHdpdGggbXVsdGlwbGUgY29ycmVjdCBhbnN3ZXJzLiBDb3VudGluZyAtIG9uZSBwb2ludCBmb3IgYSBjb3JyZWN0IGFuc3dlci4gMCBmb3Igd3JvbmcKCihDb3JyZWN0IFRlYW0gTmFtZXMpCgpgYGB7cn0KbGlicmFyeSh0aWR5cikKCmNvcnJlY3RfayA9IGMoIk5hdGlvbmFsIFN0YXRpc3RpY2FsIE9mZmljZXMgaGF2ZSByZXNlcnZhdGlvbnMgb24gdGhlIHVzZSBvZiBjaXRpemVuIHNjaWVuY2UgZGF0YSBkdWUgdG8gcXVhbGl0eSBjb25zaWRlcmF0aW9ucy4iLCAiSW1wYXJ0aWFsaXR5IChpbmRlcGVuZGVuY2UpIGFuZCBjb25maWRlbnRpYWxpdHkgYXJlIGFtb25nIGtleSBwcmluY2lwbGVzIGZvciBvZmZpY2lhbCBuYXRpb25hbCBkYXRhIHByb2R1Y2Vycy4iKQoKY29ycmVjdF9kID0gYygiQ29sbGVjdCBkYXRhIiwgIkFuYWx5emUgZGF0YSIsIlNoYXJlIG93biBkYXRhIikKCnRlbXBfcmVnID0gcmVnWyxjKCJleGFudGVfa25vd2xlZGdlIiwgImV4YW50ZV9kYXRhIiwgIlRlYW0iLCAiSUQiKV0KdGVtcF9yZWcgPSByZXNoYXBlMjo6bWVsdCh0ZW1wX3JlZywgaWQgPSBjKCJUZWFtIiwgIklEIikpCgp0ZW1wX3JlZyA9IHRlbXBfcmVnICU+JSByb3d3aXNlKCkgJT4lIG11dGF0ZShhbnN3ZXJzID0gbGlzdCh0cmltd3Moc3Ryc3BsaXQodmFsdWUsICIsIilbWzFdXSkpKSAlPiUgbXV0YXRlKGNvcnJlY3QgPSAgaWYgKHZhcmlhYmxlID09ICJleGFudGVfa25vd2xlZGdlIikgc3VtKGFuc3dlcnMgJWluJSBjb3JyZWN0X2spL2xlbmd0aChjb3JyZWN0X2spIGVsc2Ugc3VtKGFuc3dlcnMgJWluJSBjb3JyZWN0X2QpL2xlbmd0aChjb3JyZWN0X2QpLCBoeXBlciA9IGlmICh2YXJpYWJsZSA9PSAiZXhhbnRlX2tub3dsZWRnZSIpIHBoeXBlcihzdW0oYW5zd2VycyAlaW4lIGNvcnJlY3RfayksIDIsIDIsIGxlbmd0aChhbnN3ZXJzKSwgbG93ZXIudGFpbCA9IEZBTFNFKSBlbHNlIHBoeXBlcihzdW0oYW5zd2VycyAlaW4lIGNvcnJlY3RfZCksIDMsIDEsIGxlbmd0aChhbnN3ZXJzKSwgbG93ZXIudGFpbCA9IEZBTFNFKSkKCiAgI211dGF0ZShjb3JyZWN0ID0gaWYgKChzdW0oYW5zd2VycyAlaW4lIGNvcnJlY3RfaykgPT0gbGVuZ3RoKGFuc3dlcnMpICYgbGVuZ3RoKGFuc3dlcnMpID09IDIpIHx8IChzdW0oYW5zd2VycyAlaW4lIGNvcnJlY3RfZCkgPT0gbGVuZ3RoKGFuc3dlcnMpICYgbGVuZ3RoKGFuc3dlcnMpID09IDMpKSAxICBlbHNlIDApCgp0ZW1wX3JlZyR0eXBlID0gInJlZ2lzdHJhdGlvbiIKCnRlbXBfZXZhbHVhdGUgPSBhcy5kYXRhLmZyYW1lKGV2YWx1YXRlWyJleHQiXSkKY29sbmFtZXModGVtcF9ldmFsdWF0ZSkgPSBjKCJJRCIsICJUZWFtIiwgImV4YW50ZV9rbm93bGVkZ2UiLCAiZXhhbnRlX2RhdGEiKQp0ZW1wX2V2YWx1YXRlID0gcmVzaGFwZTI6Om1lbHQodGVtcF9ldmFsdWF0ZSwgaWQgPSBjKCJUZWFtIiwgIklEIikpCgp0ZW1wX2V2YWx1YXRlID0gdGVtcF9ldmFsdWF0ZSAlPiUgcm93d2lzZSgpICU+JSBtdXRhdGUoYW5zd2VycyA9IGxpc3QodHJpbXdzKHN0cnNwbGl0KHZhbHVlLCAiOyIpW1sxXV0pKSkgJT4lIG11dGF0ZShjb3JyZWN0ID0gIGlmICh2YXJpYWJsZSA9PSAiZXhhbnRlX2tub3dsZWRnZSIpIHN1bShhbnN3ZXJzICVpbiUgY29ycmVjdF9rKS9sZW5ndGgoY29ycmVjdF9rKSBlbHNlIHN1bShhbnN3ZXJzICVpbiUgY29ycmVjdF9kKS9sZW5ndGgoY29ycmVjdF9kKSwgaHlwZXIgPSBpZiAodmFyaWFibGUgPT0gImV4YW50ZV9rbm93bGVkZ2UiKSBwaHlwZXIoc3VtKGFuc3dlcnMgJWluJSBjb3JyZWN0X2spLCAyLCAyLCBsZW5ndGgoYW5zd2VycyksIGxvd2VyLnRhaWwgPSBGQUxTRSkgZWxzZSBwaHlwZXIoc3VtKGFuc3dlcnMgJWluJSBjb3JyZWN0X2QpLCAzLCAxLCBsZW5ndGgoYW5zd2VycyksIGxvd2VyLnRhaWwgPSBGQUxTRSkpCgojbXV0YXRlKGNvcnJlY3QgPSBpZiAoKHN1bShhbnN3ZXJzICVpbiUgY29ycmVjdF9rKSA9PSBsZW5ndGgoYW5zd2VycykgJiBsZW5ndGgoYW5zd2VycykgPT0gMikgfHwgKHN1bShhbnN3ZXJzICVpbiUgY29ycmVjdF9kKSA9PSBsZW5ndGgoYW5zd2VycykgJiBsZW5ndGgoYW5zd2VycykgPT0gMykpIDEgIGVsc2UgMCkKCnRlbXBfZXZhbHVhdGUkdHlwZSA9ICJldmFsdWF0ZSIKCnRlbXBfYWNjZWxlcmF0ZSA9IGFzLmRhdGEuZnJhbWUoYWNjZWxlcmF0ZVsiZXh0Il0pCmNvbG5hbWVzKHRlbXBfYWNjZWxlcmF0ZSkgPSBjKCJJRCIsICJUZWFtIiwgImV4YW50ZV9rbm93bGVkZ2UiLCAiZXhhbnRlX2RhdGEiKQp0ZW1wX2FjY2VsZXJhdGUgPSByZXNoYXBlMjo6bWVsdCh0ZW1wX2FjY2VsZXJhdGUsIGlkID0gYygiVGVhbSIsICJJRCIpKQoKdGVtcF9hY2NlbGVyYXRlID0gdGVtcF9hY2NlbGVyYXRlICU+JSByb3d3aXNlKCkgJT4lIG11dGF0ZShhbnN3ZXJzID0gbGlzdCh0cmltd3Moc3Ryc3BsaXQodmFsdWUsICI7IilbWzFdXSkpKSAlPiUgbXV0YXRlKGNvcnJlY3QgPSAgaWYgKHZhcmlhYmxlID09ICJleGFudGVfa25vd2xlZGdlIikgc3VtKGFuc3dlcnMgJWluJSBjb3JyZWN0X2spL2xlbmd0aChjb3JyZWN0X2spIGVsc2Ugc3VtKGFuc3dlcnMgJWluJSBjb3JyZWN0X2QpL2xlbmd0aChjb3JyZWN0X2QpLCBoeXBlciA9IGlmICh2YXJpYWJsZSA9PSAiZXhhbnRlX2tub3dsZWRnZSIpIHBoeXBlcihzdW0oYW5zd2VycyAlaW4lIGNvcnJlY3RfayksIDIsIDIsIGxlbmd0aChhbnN3ZXJzKSwgbG93ZXIudGFpbCA9IEZBTFNFKSBlbHNlIHBoeXBlcihzdW0oYW5zd2VycyAlaW4lIGNvcnJlY3RfZCksIDMsIDEsIGxlbmd0aChhbnN3ZXJzKSwgbG93ZXIudGFpbCA9IEZBTFNFKSkKICAKICAjbXV0YXRlKGNvcnJlY3QgPSBpZiAoKHN1bShhbnN3ZXJzICVpbiUgY29ycmVjdF9rKSA9PSBsZW5ndGgoYW5zd2VycykgJiBsZW5ndGgoYW5zd2VycykgPT0gMikgfHwgKHN1bShhbnN3ZXJzICVpbiUgY29ycmVjdF9kKSA9PSBsZW5ndGgoYW5zd2VycykgJiBsZW5ndGgoYW5zd2VycykgPT0gMykpIDEgIGVsc2UgMCkKCnRlbXBfYWNjZWxlcmF0ZSR0eXBlID0gImFjY2VsZXJhdGUiCgpgYGAKCgpgYGB7cn0KCmRmID0gcmJpbmQodGVtcF9yZWcsIHRlbXBfZXZhbHVhdGUsIHRlbXBfYWNjZWxlcmF0ZSkKZGYkdHlwZSA9IGZhY3RvcihkZiR0eXBlLCBsZXZlbHMgPSBjKCJyZWdpc3RyYXRpb24iLCAiZXZhbHVhdGUiLCAiYWNjZWxlcmF0ZSIpKQoKZGYxID0gZGZbLGMoInR5cGUiLCAidmFyaWFibGUiLCAiaHlwZXIiKV0gJT4lIGdyb3VwX2J5KHZhcmlhYmxlLCB0eXBlKSAlPiUgc3VtbWFyaXNlKG1lYW4gPSBtZWFuKGh5cGVyKSwgc2UgPSBzZShoeXBlcikpCgpwbHQgPSBnZ3Bsb3QoZGYxLCBhZXMoeCA9IHR5cGUsIHkgPSBtZWFuLCBjb2xvciA9IHZhcmlhYmxlLCBncm91cCA9IHZhcmlhYmxlKSkgKyBnZW9tX2xpbmUoKSArIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBtZWFuLXNlLCB5bWF4ID0gbWVhbitzZSksIHdpZHRoID0gMCkgKyB0aGVtZV9idyhiYXNlX3NpemUgPSAyMCkgKyB5bGFiKCJIeXBHIFAtVmFsdWUiKSArIHhsYWIoIiIpCgpnZ3NhdmUocGx0LCBmaWxlID0gIi4uL2ZpZ3VyZXMvZXhhbnRlX2NvbXBhcmVfaHlwZy5wbmciLCBoZWlnaHQgPSA3LCB3aWR0aCA9IDcpCgojKioqKiMKCmRmMSA9IGRmWyxjKCJ0eXBlIiwgInZhcmlhYmxlIiwgImNvcnJlY3QiKV0gJT4lIGdyb3VwX2J5KHZhcmlhYmxlLCB0eXBlKSAlPiUgc3VtbWFyaXNlKG1lYW4gPSBtZWFuKGNvcnJlY3QpLCBzZSA9IHNlKGNvcnJlY3QpKQoKZGYxJHZhcmlhYmxlID0gYXMuY2hhcmFjdGVyKGRmMSR2YXJpYWJsZSkKZGYxJHZhcmlhYmxlW2RmMSR2YXJpYWJsZSA9PSAiZXhhbnRlX2RhdGEiXSA9ICJEYXRhIHByb2R1Y3Rpb24gYnkgY2l0aXplbiBzY2llbnRpc3RzIgpkZjEkdmFyaWFibGVbZGYxJHZhcmlhYmxlID09ICJleGFudGVfa25vd2xlZGdlIl0gPSAiS25vd2xlZGdlIG9uIGNpdGl6ZW4gc2NpZW5jZSBkYXRhIgoKcGx0ID0gZ2dwbG90KGRmMSwgYWVzKHggPSB0eXBlLCB5ID0gbWVhbiwgY29sb3IgPSB2YXJpYWJsZSwgZ3JvdXAgPSB2YXJpYWJsZSkpICsgZ2VvbV9saW5lKCkgKyBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gbWVhbi1zZSwgeW1heCA9IG1lYW4rc2UpLCB3aWR0aCA9IDApICsgdGhlbWVfYncoYmFzZV9zaXplID0gMjApICsgeGxhYigiIikgKyB5bGFiKCJQcm9wb3J0aW9uIENvcnJlY3QgQW5zd2VyIikgKyB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpCgpnZ3NhdmUocGx0LCBmaWxlID0gIi4uL2ZpZ3VyZXMvZXhhbnRlX2NvbXBhcmUucG5nIiwgaGVpZ2h0ID0gNywgd2lkdGggPSAxMCkKCgoKYGBgCgoKMi4gVG9vbHMgYW5kIExlYXJuaW5nIGFib3V0IHRvb2xzCgpgYGB7cn0KbGlicmFyeShmbXNiKQoKcmVfdG9vbHMgPSByZWdbLGMoIklEIiwgIlRlYW0iLCAidG9vbHMiKV0KcmVfdG9vbHMkdG9vbHMgPSBhcy5jaGFyYWN0ZXIocmVfdG9vbHMkdG9vbHMpCnJlX3Rvb2xzID0gcmVfdG9vbHMgJT4lIHJvd3dpc2UoKSAlPiUgbXV0YXRlKHRvb2xzID0gbGlzdCh0cmltd3Moc3Ryc3BsaXQodG9vbHMsICIsIilbWzFdXSkpKQpyZV90b29scyA9IHVubmVzdChyZV90b29scywgY29scyA9IGMoInRvb2xzIikpCnJlX3Rvb2xzJHR5cGUgPSAicmVnaXN0cmF0aW9uIgoKZWxfdG9vbHMgPSBhcy5kYXRhLmZyYW1lKGV2YWx1YXRlWyJjc190b29scyJdKQpjb2xuYW1lcyhlbF90b29scykgPSBjKCJJRCIsICJUZWFtIiwgInZhcmlhYmxlIiwgInRvb2xzIikKZWxfdG9vbHMgPSBlbF90b29sc1tdICU+JSByb3d3aXNlKCkgJT4lIG11dGF0ZSh0b29scyA9IGxpc3QodHJpbXdzKHN0cnNwbGl0KHRvb2xzLCAiOyIpW1sxXV0pKSkgJT4lIHNlbGVjdCgtdmFyaWFibGUpCmVsX3Rvb2xzID0gdW5uZXN0KGVsX3Rvb2xzLCBjb2xzID0gYygidG9vbHMiKSkKZWxfdG9vbHMkdHlwZSA9ICJldmFsdWF0ZSIKCmFjX3Rvb2xzID0gYXMuZGF0YS5mcmFtZShhY2NlbGVyYXRlWyJjc190b29scyJdKQpjb2xuYW1lcyhhY190b29scykgPSBjKCJJRCIsICJUZWFtIiwgInZhcmlhYmxlIiwgInRvb2xzIikKYWNfdG9vbHMgPSBhY190b29sc1tdICU+JSByb3d3aXNlKCkgJT4lIG11dGF0ZSh0b29scyA9IGxpc3QodHJpbXdzKHN0cnNwbGl0KHRvb2xzLCAiOyIpW1sxXV0pKSkgJT4lIHNlbGVjdCgtdmFyaWFibGUpCmFjX3Rvb2xzID0gdW5uZXN0KGFjX3Rvb2xzLCBjb2xzID0gYygidG9vbHMiKSkKYWNfdG9vbHMkdHlwZSA9ICJhY2NlbGVyYXRlIgoKYGBgCgpSYWRhciBQbG90IC0gQWxsIHRlYW1zCgpgYGB7cn0KCnJlX3Rvb2xzID0gbWVyZ2UocmVfdG9vbHMsIHJlZ19tYXAsIGJ5LnggPSAiVGVhbSIsIGJ5LnkgPSAib2xkX25hbWUiLCBhbGwueCA9IFRSVUUpCnJlX3Rvb2xzJFRlYW0gPSByZV90b29scyRuZXdfbmFtZQoKcmVfdG9vbHMgPSByZV90b29scyAlPiUgc2VsZWN0KC1uZXdfbmFtZSkKCnRvb2xzID0gcmJpbmQocmVfdG9vbHMsIGVsX3Rvb2xzLCBhY190b29scykKdG9vbHMkdG9vbHNbdG9vbHMkdG9vbHMgPT0gIk5vbmUgb2YgdGhlIGFib3ZlIl0gPSAiTm9uZSIKCnRlbXAgPSB0b29scyAlPiUgZ3JvdXBfYnkodG9vbHMsIHR5cGUpICU+JSBzdW1tYXJpc2UoY291bnQgPSBuKCkpCnRlbXAgPSB0ZW1wICU+JSBncm91cF9ieSh0eXBlKSAlPiUgbXV0YXRlKGNvdW50ID0gY291bnQvc3VtKGNvdW50KSkKdGVtcCA9IHJlc2hhcGUyOjphY2FzdCh0ZW1wLCB0eXBlfnRvb2xzKQp0ZW1wW2lzLm5hKHRlbXApXSA9IDAKCnRlbXAgPSByYmluZChyZXAoMSwgbmNvbCh0ZW1wKSksIHJlcCgwLG5jb2wodGVtcCkpLCB0ZW1wKQp0ZW1wID0gYXMuZGF0YS5mcmFtZSh0ZW1wKQoKY29sb3JzX2JvcmRlcj1jKCByZ2IoMC4yLDAuNSwwLjUsMC45KSwgcmdiKDAuOCwwLjIsMC41LDAuOSkgLCByZ2IoMC43LDAuNSwwLjEsMC45KSApCmNvbG9yc19pbj1jKCByZ2IoMC4yLDAuNSwwLjUsMC40KSwgcmdiKDAuOCwwLjIsMC41LDAuNCkgLCByZ2IoMC43LDAuNSwwLjEsMC40KSApCgpwZGYoIi4uL2ZpZ3VyZXMvcmFkYXJfc3RhZ2UucGRmIiwgcGFwZXI9ImE0ciIsIHdpZHRoPTEwLCBoZWlnaHQ9MTApCgpyYWRhcmNoYXJ0KCBhcy5kYXRhLmZyYW1lKHRlbXApLCBheGlzdHlwZT0xICwgCiAgICAjY3VzdG9tIHBvbHlnb24KICAgIHBjb2w9Y29sb3JzX2JvcmRlciAsIHBmY29sPWNvbG9yc19pbiAsIHBsd2Q9NCAsIHBsdHk9MSwKICAgICNjdXN0b20gdGhlIGdyaWQKICAgIGNnbGNvbD0iZ3JleSIsIGNnbHR5PTEsIGF4aXNsYWJjb2w9ImdyZXkiLCBjZ2x3ZD0wLjgsCiAgICAjY3VzdG9tIGxhYmVscwogICAgdmxjZXg9MS41IAogICAgKQoKbGVnZW5kKHg9MS4yLCB5PTEsIGxlZ2VuZCA9IHJvd25hbWVzKHRlbXBbYyg1LDQsMyksXSksIGJ0eSA9ICJuIiwgcGNoPTIwICwgY29sPWNvbG9yc19pbltjKDMsMiwxKV0gLCB0ZXh0LmNvbCA9ICJncmV5IiwgY2V4PTEuMiwgcHQuY2V4PTMpCgpkZXYub2ZmKCkKCmBgYApPbmx5IFRlYW1zIGluIEFjY2VsZXJhdGUKCmBgYHtyfQoKdGVtcCA9IHRvb2xzW3Rvb2xzJFRlYW0gJWluJSB1bmlxdWUodG9vbHMkVGVhbVt0b29scyR0eXBlID09ICJhY2NlbGVyYXRlIl0pLF0KdGVtcCA9IHRlbXAgJT4lIGdyb3VwX2J5KHRvb2xzLCB0eXBlKSAlPiUgc3VtbWFyaXNlKGNvdW50ID0gbigpKQoKdGVtcCA9IHRlbXAgJT4lIGdyb3VwX2J5KHR5cGUpICU+JSBtdXRhdGUoY291bnQgPSBjb3VudC9zdW0oY291bnQpKSAKdGVtcCA9IHJlc2hhcGUyOjphY2FzdCh0ZW1wLCB0eXBlfnRvb2xzKQp0ZW1wW2lzLm5hKHRlbXApXSA9IDAKCnRlbXAgPSByYmluZChyZXAoMSwgbmNvbCh0ZW1wKSksIHJlcCgwLG5jb2wodGVtcCkpLCB0ZW1wKQp0ZW1wID0gYXMuZGF0YS5mcmFtZSh0ZW1wKQoKY29sb3JzX2JvcmRlcj1jKCByZ2IoMC4yLDAuNSwwLjUsMC45KSwgcmdiKDAuOCwwLjIsMC41LDAuOSkgLCByZ2IoMC43LDAuNSwwLjEsMC45KSApCmNvbG9yc19pbj1jKCByZ2IoMC4yLDAuNSwwLjUsMC40KSwgcmdiKDAuOCwwLjIsMC41LDAuNCkgLCByZ2IoMC43LDAuNSwwLjEsMC40KSApCgpwZGYoIi4uL2ZpZ3VyZXMvcmFkYXJfdGVhbXMucGRmIiwgcGFwZXI9ImE0ciIsIHdpZHRoPTEwLCBoZWlnaHQ9MTApCgpyYWRhcmNoYXJ0KCBhcy5kYXRhLmZyYW1lKHRlbXApLCBheGlzdHlwZT0xICwgCiAgICAjY3VzdG9tIHBvbHlnb24KICAgIHBjb2w9Y29sb3JzX2JvcmRlciAsIHBmY29sPWNvbG9yc19pbiAsIHBsd2Q9NCAsIHBsdHk9MSwKICAgICNjdXN0b20gdGhlIGdyaWQKICAgIGNnbGNvbD0iZ3JleSIsIGNnbHR5PTEsIGF4aXNsYWJjb2w9ImdyZXkiLCBjZ2x3ZD0wLjgsCiAgICAjY3VzdG9tIGxhYmVscwogICAgdmxjZXg9MS41IAogICAgKQoKbGVnZW5kKHg9MS4yLCB5PTEsIGxlZ2VuZCA9IHJvd25hbWVzKHRlbXBbYyg1LDQsMyksXSksIGJ0eSA9ICJuIiwgcGNoPTIwICwgY29sPWNvbG9yc19pbltjKDMsMiwxKV0gLCB0ZXh0LmNvbCA9ICJncmV5IiwgY2V4PTEuMiwgcHQuY2V4PTMpCgpkZXYub2ZmKCkKCmBgYAoKMy4gIEhvdyBPZnRlbiBkaWQgeW91IGNvbm5lY3Qgd2l0aCByZWxldmFudCBwZW9wbGUKCmBgYHtyfQoKZWxfaG8gPSBhcy5kYXRhLmZyYW1lKGV2YWx1YXRlWyJoX28iXSkKY29sbmFtZXMoZWxfaG8pID0gYygiSUQiLCAiVGVhbSIsICJ2YXJpYWJsZSIsICJ2YWx1ZSIsICJzY29yZSIpCmVsX2hvJHR5cGUgPSAiZXZhbHVhdGUiCgoKYWNfaG8gPSBhcy5kYXRhLmZyYW1lKGFjY2VsZXJhdGVbImhfbyJdKQpjb2xuYW1lcyhhY19obykgPSBjKCJJRCIsICJUZWFtIiwgInZhcmlhYmxlIiwgInZhbHVlIiwgInNjb3JlIikKYWNfaG8kdHlwZSA9ICJhY2NlbGVyYXRlIgoKCmBgYAoKCgpgYGB7cn0KCmhvID0gcmJpbmQoZWxfaG8sIGFjX2hvKQpobyR0eXBlID0gZmFjdG9yKGhvJHR5cGUsIGxldmVscyA9IGMoImV2YWx1YXRlIiwgImFjY2VsZXJhdGUiKSkKCnZhbCA9IHNvcnQoZmFjdG9yKHVuaXF1ZShobyR2YWx1ZSksIGxldmVscyA9IGMoIk5ldmVyIiwgIkxlc3MgdGhhbiBvbmNlIGEgd2VlayIsICJPbmNlIGEgd2VlayIsICJUd28gdG8gdGhyZWUgdGltZXMgYSB3ZWVrIiwgIkZvdXIgdGltZXMgb3IgbW9yZSBhIHdlZWsiKSkpCgpob190ID0gaG8gJT4lIGdyb3VwX2J5KHR5cGUsIHZhcmlhYmxlKSAlPiUgc3VtbWFyaXNlKG1lYW4gPSBtZWFuKHNjb3JlKSwgc2UgPSBzZShzY29yZSkpCgpwbHQgPSBnZ3Bsb3QoaG9fdCwgYWVzKHggPSB2YXJpYWJsZSwgeSA9IG1lYW4sIGZpbGwgPSB0eXBlLCBjb2xvciA9IHR5cGUpKSArIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuMywgcHJlc2VydmUgPSAidG90YWwiKSkgKyBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gbWVhbi1zZSwgeW1heCA9IG1lYW4rc2UpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC4zLCBwcmVzZXJ2ZSA9ICJ0b3RhbCIpLCB3aWR0aCA9IDApICsgdGhlbWVfYncoYmFzZV9zaXplID0gMjIpICsgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1jKDA6NCksIGJyZWFrcz0wOjQsIGxpbWl0cz1jKDAsNCkpICsgeWxhYigiIikgKyB4bGFiKCIiKSArIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkKCmdncGxvdGx5KHBsdCkKCmdnc2F2ZShwbHQsIGZpbGVuYW1lID0gIi4uL2ZpZ3VyZXMvaG93X29mdGVuX2NvbXBhcmUucG5nIiwgd2lkdGggPSAxMCwgaGVpZ2h0ID0gNSkKCmBgYAoKQnkgVGVhbTEKCmBgYHtyfQoKaG8kc3RhdHVzID0gImV2YWx1YXRlIgpobyRzdGF0dXNbaG8kVGVhbSAlaW4lIHVuaXF1ZShobyRUZWFtW2hvJHR5cGUgPT0gImFjY2VsZXJhdGUiXSldID0gImFjY2VsZXJhdGUiCgpobyRzdGF0dXMgPSBmYWN0b3IoaG8kc3RhdHVzLCBsZXZlbHMgPSBjKCJldmFsdWF0ZSIsICJhY2NlbGVyYXRlIikpCgpob190ID0gaG8gJT4lIGdyb3VwX2J5KHR5cGUsIHZhcmlhYmxlLCBzdGF0dXMpICU+JSBzdW1tYXJpc2UobWVhbiA9IG1lYW4oc2NvcmUpLCBzZSA9IHNlKHNjb3JlKSwgY291bnQgPSBuKCkpCgpwbHQgPSBnZ3Bsb3QoaG9fdFtob190JHR5cGUgPT0gImV2YWx1YXRlIixdLCBhZXMoeCA9IHZhcmlhYmxlLCB5ID0gbWVhbiwgZmlsbCA9IHN0YXR1cywgY29sb3IgPSBzdGF0dXMpKSArIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuMywgcHJlc2VydmUgPSAidG90YWwiKSkgKyBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gbWVhbi1zZSwgeW1heCA9IG1lYW4rc2UpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC4zLCBwcmVzZXJ2ZSA9ICJ0b3RhbCIpLCB3aWR0aCA9IDApICsgdGhlbWVfYncoYmFzZV9zaXplID0gMjIpICArIHlsYWIoIiIpICsgeGxhYigiIikgKyBnZ3RpdGxlKCJIb3cgb2Z0ZW4gZGlkIHlvdSBjb25uZWN0IHdpdGggdGhlc2UgcGVvcGxlIFxuIGZvciBmZWVkYmFjayBhbmQgc3VwcG9ydCBmb3IgeW91ciB0ZWFtIHByb2plY3Q/IikgKyBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPXZhbCwgYnJlYWtzPTA6NCwgbGltaXRzPWMoMCw0KSkrIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplID0gMjApKQoKZ2dwbG90bHkocGx0KQoKZ2dzYXZlKHBsdCwgZmlsZW5hbWUgPSAiLi4vZmlndXJlcy9ob3dfb2Z0ZW5fZXZhbHVhdGUucG5nIiwgd2lkdGggPSAxMCwgaGVpZ2h0ID0gNSkKCmBgYAoKQ29tbXVuaWNhdGlvbiBUb29scyAoTm8gU2xhY2sgb3B0aW9uIGluIGV2YWx1YXRlIC0gVGhlcmUgaXMgT3RoZXIgbGlzdGVkLCBidXQgZnJlcXVlbmN5IGlzIHVuc3VyZSkKCmBgYHtyfQoKZWxfd2MgPSBhcy5kYXRhLmZyYW1lKGV2YWx1YXRlWyJ3X2MiXSkKY29sbmFtZXMoZWxfd2MpID0gYygiSUQiLCAiVGVhbSIsICJ2YXJpYWJsZSIsICJ2YWx1ZSIsICJzY29yZSIpCmVsX3djJHR5cGUgPSAiZXZhbHVhdGUiCgphY193YyA9IGFzLmRhdGEuZnJhbWUoYWNjZWxlcmF0ZVsid19jIl0pCmNvbG5hbWVzKGFjX3djKSA9IGMoIklEIiwgIlRlYW0iLCAidmFyaWFibGUiLCAidmFsdWUiLCAic2NvcmUiKQphY193YyR0eXBlID0gImFjY2VsZXJhdGUiCgp3YyA9IHJiaW5kKGVsX3djLCBhY193YykKCnZhbCA9IHNvcnQoZmFjdG9yKHVuaXF1ZSh3YyR2YWx1ZSksIGxldmVscyA9IGMoIk5ldmVyIiwgIlJhcmVseSIsICJTb21ldGltZXMiLCAiT2Z0ZW4iLCAiQWx3YXlzIikpKQoKd2NfdCA9IHdjICU+JSBncm91cF9ieSh0eXBlLCB2YXJpYWJsZSkgJT4lIHN1bW1hcmlzZShtZWFuID0gbWVhbihzY29yZSksIHNlID0gc2Uoc2NvcmUpKQoKcGx0ID0gZ2dwbG90KHdjX3RbIXdjX3QkdmFyaWFibGUgPT0gIk90aGVyLi4uc3BlY2lmeS5pbi5uZXh0LnF1ZXN0aW9uLi4iLF0sIGFlcyh4ID0gdmFyaWFibGUsIHkgPSBtZWFuLCBmaWxsID0gdHlwZSwgY29sb3IgPSB0eXBlKSkgKyBnZW9tX3BvaW50KHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjMsIHByZXNlcnZlID0gInRvdGFsIikpICsgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IG1lYW4tc2UsIHltYXggPSBtZWFuK3NlKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuMywgcHJlc2VydmUgPSAidG90YWwiKSwgd2lkdGggPSAwKSArIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDIwKSArIHNjYWxlX3lfY29udGludW91cyhsYWJlbHM9dmFsLCBicmVha3M9MDo0LCBsaW1pdHM9YygwLDQpKSArIHlsYWIoIiIpICsgeGxhYigiIikgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1KSkrIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkKCmdncGxvdGx5KHBsdCkKYGBgCgpJc3N1ZXMgKG5vdCB2ZXJ5IGhlbHBmdWwpCgpgYGB7cn0KCmVsX2RpID0gYXMuZGF0YS5mcmFtZShldmFsdWF0ZVsiZF9pIl0pCmNvbG5hbWVzKGVsX2RpKSA9IGMoIklEIiwgIlRlYW0iLCAidmFyaWFibGUiLCAidmFsdWUiLCAic2NvcmUiKQplbF9kaSR0eXBlID0gImV2YWx1YXRlIgoKYWNfZGkgPSBhcy5kYXRhLmZyYW1lKGFjY2VsZXJhdGVbImRfaSJdKQpjb2xuYW1lcyhhY19kaSkgPSBjKCJJRCIsICJUZWFtIiwgInZhcmlhYmxlIiwgInZhbHVlIiwgInNjb3JlIikKYWNfZGkkdHlwZSA9ICJhY2NlbGVyYXRlIgoKZGkgPSByYmluZChlbF9kaSwgYWNfZGkpCmRpJHR5cGUgPSBmYWN0b3IoZGkkdHlwZSwgbGV2ZWxzID0gYygiZXZhbHVhdGUiLCAiYWNjZWxlcmF0ZSIpKQoKdmFsID0gc29ydChmYWN0b3IodW5pcXVlKGRpJHZhbHVlKSwgbGV2ZWxzID0gYygiTmV2ZXIiLCAiUmFyZWx5IiwgIlNvbWV0aW1lcyIsICJPZnRlbiIsICJBbHdheXMiKSkpCgpkaV90ID0gZGkgJT4lIGdyb3VwX2J5KHR5cGUsIHZhcmlhYmxlKSAlPiUgc3VtbWFyaXNlKG1lYW4gPSBtZWFuKHNjb3JlKSwgc2UgPSBzZShzY29yZSkpCgpwbHQgPSBnZ3Bsb3QoZGlfdCwgYWVzKHggPSB2YXJpYWJsZSwgeSA9IG1lYW4sIGZpbGwgPSB0eXBlLCBjb2xvciA9IHR5cGUpKSArIGdlb21fcG9pbnQocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuMywgcHJlc2VydmUgPSAidG90YWwiKSkgKyBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gbWVhbi1zZSwgeW1heCA9IG1lYW4rc2UpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC4zLCBwcmVzZXJ2ZSA9ICJ0b3RhbCIpLCB3aWR0aCA9IDApICsgdGhlbWVfYncoYmFzZV9zaXplID0gMjApICArIHlsYWIoIiIpICsgeGxhYigiIikgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDApKSArIHNjYWxlX3lfY29udGludW91cyhsYWJlbHM9dmFsLCBicmVha3M9MDo0LCBsaW1pdHM9YygwLDQpKSsgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKQoKZ2dwbG90bHkocGx0KQoKZ2dzYXZlKHBsdCwgZmlsZW5hbWUgPSAiLi4vZmlndXJlcy9oYWRfaXNzdWVzX2NvbXBhcmUucG5nIiwgd2lkdGggPSAxMCwgaGVpZ2h0ID0gNykKCmBgYAoKSXNzdWVzIChPbmx5IEFjY2VsZXJhdGUgVGVhbXMpCgpgYGB7cn0KCmRpX3QgPSBkaVtkaSRUZWFtICVpbiUgdW5pcXVlKGRpJFRlYW1bZGkkdHlwZSA9PSAiYWNjZWxlcmF0ZSJdKSxdICU+JSBncm91cF9ieSh0eXBlLCB2YXJpYWJsZSkgJT4lIHN1bW1hcmlzZShtZWFuID0gbWVhbihzY29yZSksIHNlID0gc2Uoc2NvcmUpKQoKcGx0ID0gZ2dwbG90KGRpX3QsIGFlcyh4ID0gdmFyaWFibGUsIHkgPSBtZWFuLCBmaWxsID0gdHlwZSwgY29sb3IgPSB0eXBlKSkgKyBnZW9tX3BvaW50KHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjMsIHByZXNlcnZlID0gInRvdGFsIikpICsgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IG1lYW4tc2UsIHltYXggPSBtZWFuK3NlKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuMywgcHJlc2VydmUgPSAidG90YWwiKSwgd2lkdGggPSAwKSArIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDIwKSAgKyB5bGFiKCIiKSArIHhsYWIoIiIpICsgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwKSkgKyBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPXZhbCwgYnJlYWtzPTA6NCwgbGltaXRzPWMoMCw0KSkrIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkKCmdncGxvdGx5KHBsdCkKCmdnc2F2ZShwbHQsIGZpbGVuYW1lID0gIi4uL2ZpZ3VyZXMvaGFkX2lzc3Vlc19jb21wYXJlX2FjY190ZWFtcy5wbmciLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSA3KQoKYGBgCgpHZW5kZXIgQW5hbHlzaXMKCmBgYHtyfQoKYWNjX3RlYW0gPSBhcy5jaGFyYWN0ZXIodW5pcXVlKGFjY2VsZXJhdGVbWzFdXSRXaGF0LmlzLnlvdXIudGVhbS4pKQoKZ2VuID0gcmVnWyxjKCJnZW5kZXIiLCAiVGVhbSIpXQojZ2VuJFRlYW1sID0gcmVnX21hcFtnZW4kVGVhbV0KZ2VuID0gbWVyZ2UoZ2VuLCByZWdfbWFwLCBieS54ID0gIlRlYW0iLCBieS55ID0gIm9sZF9uYW1lIiwgYWxsLnggPSBUUlVFKQpnZW4kVGVhbSA9IGdlbiRuZXdfbmFtZQpnZW4gPSBnZW4gJT4lIHNlbGVjdCgtbmV3X25hbWUpCgp0ZW1wID0gZ2VuICU+JSBncm91cF9ieShUZWFtLCBnZW5kZXIpICU+JSBzdW1tYXJpc2UoY291bnQgPSBuKCkpCgp0ZW1wJHR5cGUgPSAxCnRlbXAkdHlwZVt0ZW1wJFRlYW0gJWluJSBhY2NfdGVhbV0gPSAyCgpjb2wgPSB3ZXNfcGFsZXR0ZSgiR3JhbmRCdWRhcGVzdDEiLCAzKQojY29sID0gaHAobiA9IDMsIG9wdGlvbiA9ICJMdW5hTG92ZWdvb2QiKQoKdGVtcCRnZW5kZXIgPSBmYWN0b3IodGVtcCRnZW5kZXIsIGxldmVscyA9IGMoIlByZWZlciBub3QgdG8gc2F5IiwgIk1hbGUiLCAiRmVtYWxlIiApKQoKcGx0ID0gZ2dwbG90KHRlbXAsIGFlcyh4ID0gY291bnQsIHkgPSByZW9yZGVyKFRlYW0sIHR5cGUpLCBmaWxsID0gZ2VuZGVyKSkgKyBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKyB0aGVtZV9idyhiYXNlX3NpemUgPSAyMikgKyB5bGFiKCIiKSArIHhsYWIoIiIpICsgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYyhjb2xbMV0sIGNvbFsyXSwgY29sWzNdKSkgKyB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpICMrIGdlb21fdGV4dChzdGF0PSdpZGVudGl0eScsIGFlcyhsYWJlbD0gY291bnQpLCBoanVzdD0tMSkKCmdncGxvdGx5KHBsdCkKCmdnc2F2ZShwbHQsIGZpbGVuYW1lID0gIi4uL2ZpZ3VyZXMvZ2VuZGVyX2Rpc3QucG5nIiwgaGVpZ2h0ID0gNSwgd2lkdGggPSAxNSkKCmBgYAoKCkJhY2tncm91bmQgUmFkYXIKCmBgYHtyfQoKYmFjayA9IHJlZ1sgLGMoIm5ld19uYW1lIiwgImJhY2tncm91bmQiKV0KCmJhY2sgPSBjbGVhbl9zcGxpdF9tY3EoYmFjaykKY29sbmFtZXMoYmFjaykgPSBjKCJUZWFtIiwgImJnciIpCgojYmFjayRiYWNrZ3JvdW5kID0gYXMuY2hhcmFjdGVyKGJhY2skYmFja2dyb3VuZCkKI2JhY2sgPSBiYWNrICU+JSByb3d3aXNlKCkgJT4lIG11dGF0ZShiZ3IgPSBsaXN0KHRyaW13cyhzdHJzcGxpdChiYWNrZ3JvdW5kLCAiLCIpW1sxXV0pKSkKCiNiYWNrID0gdW5uZXN0KGJhY2ssIGNvbHMgPSBjKCJiZ3IiKSkKCmBgYAoKYGBge3J9Cgp0ZW1wID0gYmFja1tiYWNrJFRlYW0gJWluJSBhY2NfdGVhbSxdICU+JSBncm91cF9ieShiZ3IsIFRlYW0pICU+JSBzdW1tYXJpc2UoY291bnQgPSBuKCkpCgp0ZW1wID0gcmVzaGFwZTI6OmFjYXN0KHRlbXAsIGZvcm11bGEgPSBUZWFtfmJncikKdGVtcFtpcy5uYSh0ZW1wKV0gPSAwCgp0ZW1wID0gcmJpbmQocmVwKDQsIG5jb2wodGVtcCkpLCByZXAoMCxuY29sKHRlbXApKSwgdGVtcCkKdGVtcCA9IGFzLmRhdGEuZnJhbWUodGVtcCkKCiNjb2xvcnNfYm9yZGVyPWMoIHJnYigwLjIsMC41LDAuNSwwLjkpLCByZ2IoMC44LDAuMiwwLjUsMC45KSAsIHJnYigwLjcsMC41LDAuMSwwLjkpICkKI2NvbG9yc19pbj1jKCByZ2IoMC4yLDAuNSwwLjUsMC40KSwgcmdiKDAuOCwwLjIsMC41LDAuNCkgLCByZ2IoMC43LDAuNSwwLjEsMC40KSApCgpwbmcoZmlsZW5hbWUgPSAiLi4vZmlndXJlcy9yZWdfYmFja2dyb3VuZC5wbmciKQoKcmFkYXJjaGFydCggYXMuZGF0YS5mcmFtZSh0ZW1wKSwgYXhpc3R5cGU9MSAsIAogICAgI2N1c3RvbSBwb2x5Z29uCiAgICBwbHdkPTQgLCBwbHR5PTEsCiAgICAjY3VzdG9tIHRoZSBncmlkCiAgICBjZ2xjb2w9ImdyZXkiLCBjZ2x0eT0xLCBheGlzbGFiY29sPSJncmV5IiwgY2dsd2Q9MC44LAogICAgI2N1c3RvbSBsYWJlbHMKICAgIHZsY2V4PTAuNSAKICAgICkKCmxlZ2VuZCh4PTEuNCwgeT0xLCBsZWdlbmQgPSByb3duYW1lcyh0ZW1wW2MoNSw0LDMpLF0pLCBidHkgPSAibiIsIHBjaD0yMCAsIGNvbD1jb2xvcnNfaW5bYygzLDIsMSldICwgdGV4dC5jb2wgPSAiZ3JleSIsIGNleD0xLjIsIHB0LmNleD0zKQoKZGV2Lm9mZigpCgpgYGAKCgoKClNhbmtleSBOZXR3b3JrcwoKYGBge3J9CgpsaWJyYXJ5KG5ldHdvcmtEMykKbGlicmFyeShyYm9rZWgpCmxpYnJhcnkod2Vic2hvdCkKCmZvciAoaSBpbiBjKCJnZW5kZXIiLCAiY291bnRyeV9vcmlnIiwgImNvdW50cnlfcmVzaWQiLCAiZWR1Y2F0aW9uIiwgImNvbW11bmljYXRpb24iLCAiZXhhbnRlX3Byb2plY3RfU0RHIiwgImJhY2tncm91bmQiLCAib2NjdXBhdGlvbiIpKQp7CiAgCiAgdGVtcCA9IHJlZ1sgLGMoIm5ld19uYW1lIiwgaSldCiAgCiAgdGVtcCA9IGNsZWFuX3NwbGl0X21jcSh0ZW1wKQogIGNvbG5hbWVzKHRlbXApID0gYygiVGVhbSIsICJ2YXIiKQogIAogIG5vZGVzID0gZGF0YS5mcmFtZShOYW1lID0gdW5pb24odW5pcXVlKHRlbXAkVGVhbSksIHVuaXF1ZSh0ZW1wJHZhcikpKQoKICBsaW5rcyA9IHRlbXAgJT4lIGdyb3VwX2J5KFRlYW0sIHZhcikgJT4lIHN1bW1hcmlzZShjb3VudCA9IG4oKSkKICBsaW5rcyRJRHNvdXJjZSA8LSBtYXRjaChsaW5rcyRUZWFtLCBub2RlcyROYW1lKS0xIAogIGxpbmtzJElEdGFyZ2V0IDwtIG1hdGNoKGxpbmtzJHZhciwgbm9kZXMkTmFtZSktMQoKICBwbHQgPSBzYW5rZXlOZXR3b3JrKExpbmtzID0gbGlua3MsIE5vZGVzID0gbm9kZXMsCiAgICAgICAgICAgICAgICAgICAgIFNvdXJjZSA9ICJJRHNvdXJjZSIsIFRhcmdldCA9ICJJRHRhcmdldCIsCiAgICAgICAgICAgICAgICAgICAgIFZhbHVlID0gImNvdW50IiwgTm9kZUlEID0gIk5hbWUiLCAKICAgICAgICAgICAgICAgICAgICAgc2lua3NSaWdodD1GQUxTRSwgZm9udFNpemUgPSAxNSkKICAjcGx0CiAgCiAgdmlzU2F2ZShwbHQsIHBhc3RlKCIuLi9maWd1cmVzL3NhbmtleS8iLCBpLCAiX3JlZy5odG1sIiwgc2VwID0gIiIpKQogICN3aWRnZXQycG5nKHBsdCwgcGFzdGUoIi4uL2ZpZ3VyZXMvc2Fua2V5LyIsIGksICJfcmVnLnBuZyIsIHNlcCA9ICIiKSkKICAKICB3ZWJzaG90KHBhc3RlKCIuLi9maWd1cmVzL3NhbmtleS8iLCBpLCAiX3JlZy5odG1sIiwgc2VwID0gIiIpLCBwYXN0ZSgiLi4vZmlndXJlcy9zYW5rZXkvIiwgaSwgIl9yZWcucG5nIiwgc2VwID0gIiIpKQp9CgpgYGAKCkFnZSBieSBHZW5kZXIKCmBgYHtyfQoKcmVnJGFnZSA9IGZsb29yKGFzLm51bWVyaWMoZGlmZnRpbWUoYXMuRGF0ZSgiMjAyMi0wNC0wMSIpLCBhcy5EYXRlKHJlZyRiaXJ0aGRheSwgdHJ5Rm9ybWF0cyA9IGMoIiVtLyVkLyVZIikpLCB1bml0PSJ3ZWVrcyIpKS81Mi4yNSkKCnBsdCA9IGdncGxvdChyZWcsIGFlcyh4ID0gZ2VuZGVyLCB5ID0gYWdlKSkgKyBnZW9tX2JveHBsb3QoZmlsbCA9ICJncmF5IikgKyB0aGVtZV9idyhiYXNlX3NpemUgPSAyMCkgKyB4bGFiKCIiKSArIHlsYWIoIkFnZSIpICsgZ2VvbV9wb2ludChhZXMoeCA9IGdlbmRlciwgeSA9IGFnZSksIGFscGhhID0gMC4yKQpnZ3Bsb3RseShwbHQpCgpnZ3NhdmUocGx0LCBmaWxlbmFtZSA9ICIuLi9maWd1cmVzL2FnZV9nZW5kZXIucG5nIiwgaGVpZ2h0ID0gNywgd2lkdGggPSA1KQpgYGAKCg==